﻿using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
using Microsoft.Graphics.Canvas.UI.Xaml;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.ApplicationModel.DataTransfer;
using Windows.Foundation;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Documents;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using 纸片人.CalculateControls;
using 纸片人.ConvertClass;
using 纸片人.InterfaceFolder;
using 纸片人.win2dEffectControl.DataClass;


// The Templated Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234235

namespace 纸片人.win2dEffectControl
{
    public abstract class EffectOutputControl : ProviderDataControl, IEffectPropertyChanged
    {


        protected Panel controlContainer;

        #region 顶部控件
        protected TextBlock effectBlockName;
        public ExporterDragControl exporterDrag;
        protected Panel outputPanel;
        #endregion

        #region 底部控件
        protected CheckBox displayCheckBox;
        //protected CanvasAnimatedControl canvas;
        protected CanvasControl canvas;

        

        #endregion

        protected bool canvasVisible = true;
        public int effectWidth;
        public int effectHeight;

        public static OutputData outputData = null;
        public static CanvasDevice device = new CanvasDevice();
        protected CanvasRenderTarget displayTarget;



        /// <summary>
        /// 当前效果输出到的控件
        /// </summary>
        public ICanvasImage Effect { get; set; }
        //public EffectData EffectData;


        #region EffectData     
        /// <summary>
        /// 获取或设置EffectData的值
        /// </summary>  
        public EffectData EffectData
        {
            get { return (EffectData)GetValue(EffectDataProperty); }
            set { SetValue(EffectDataProperty, value); }
        }

        /// <summary>
        /// 标识 EffectData 依赖属性。
        /// </summary>
        public static readonly DependencyProperty EffectDataProperty =
            DependencyProperty.Register("EffectData", typeof(EffectData), typeof(EffectOutputControl), new PropertyMetadata(null, OnEffectDataChanged));

        private static void OnEffectDataChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            EffectOutputControl target = obj as EffectOutputControl;
            EffectData oldValue = (EffectData)args.OldValue;
            EffectData newValue = (EffectData)args.NewValue;
            if (oldValue != newValue)
                target.OnEffectDataChanged(oldValue, newValue);
        }

        protected virtual void OnEffectDataChanged(EffectData oldValue, EffectData newValue)
        {
        }
        #endregion


        public event PropertyChangedHeader EffectChanged;
       

        public EffectOutputControl()
        {
            this.DefaultStyleKey = typeof(EffectOutputControl);
            this.Loaded += EffectOutputControl_Loaded;
        }

        private void EffectOutputControl_Loaded(object sender, RoutedEventArgs e)
        {
            ///获取所有输入的子控件
            foreach (var item in listProviderExportChild)
            {
                item.IsExporter = false;
                if(item is RangeControl rc)
                {
                    rc.IsChildVisible = Visibility.Collapsed;
                }
            }
        }

        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            controlContainer = GetTemplateChildFormName<Panel>(nameof(controlContainer));
            if (controlContainer == null)
            {
                return;
            }
            SetHeaderPanel();
            SetOutputPanel();
        }



        protected void Canvas_Draw(CanvasControl sender, CanvasDrawEventArgs args)
        {
            CanvasDraw(sender, args);
        }


        /// <summary>
        /// 绘制图像
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        protected virtual void CanvasDraw(CanvasControl sender, CanvasDrawEventArgs args)
        {

            Effect = EffectData.GetEffect(canvas.Device, true);
            if (Effect == null)
            {
                using (var ds = args.DrawingSession)
                {
                    ds.Clear(Colors.Transparent);
                    Function.DrawGridGraphics(ds,  10);
                }
                return;
            }
            var width = sender.ActualWidth;
            var height = sender.ActualHeight;
            using (var ds = args.DrawingSession)

            {
                ds.Clear(Colors.Transparent);
                Function.DrawGridGraphics(ds,  10);
                Rect bounds;
                bounds.Width = EffectData.Size.Width;
                bounds.Height = EffectData.Size.Height;
                var wf = width / bounds.Width;
                var hf = height / bounds.Height;
                var f = wf < hf ? wf : hf;
                var x = (float)(width - f * bounds.Width) / 2;
                var y = (float)(height - f * bounds.Height) / 2;
                Transform2DEffect te = new Transform2DEffect();
                te.Source = Effect;
                te.TransformMatrix = Matrix3x2.CreateScale((float)f) * Matrix3x2.CreateTranslation(x, y);
                ds.DrawImage(te);
            }
        }



        private void SetHeaderPanel()
        {
            outputPanel = new RelativePanel();
            effectBlockName = new TextBlock()
            {
                Text = "这里写控件名：",
                VerticalAlignment = VerticalAlignment.Center
            };
            exporterDrag = new ExporterDragControl()
            {
                CanDrag = true,
            };

            exporterDrag.DragStarting += exporterDrag_DragStarting;
            RelativePanel.SetAlignLeftWithPanel(effectBlockName, true);
            RelativePanel.SetLeftOf(effectBlockName, exporterDrag);

            RelativePanel.SetAlignRightWithPanel(exporterDrag, true);

            outputPanel.Children.Add(effectBlockName);
            outputPanel.Children.Add(exporterDrag);

            controlContainer.Children.Insert(0, outputPanel);



        }

       

        protected override void Timer_Tick(object sender, object e)
        {
            if (EffectData == null || !canvasVisible)
            {
                return;
            }
            //首先判断是否有修改过效果信息
            if (EffectData.GetIsChanges(EffectData))
            {
                canvas.Invalidate();
            }
        }


        /// <summary>
        /// 设置效果名
        /// </summary>
        protected void SetEffectName(string name, object tool)
        {
            effectBlockName.Text = name;
            ToolTipService.SetToolTip(effectBlockName, tool);
        }

        /// <summary>
        /// 添加控件底部显示图片控件
        /// </summary>
        private void SetOutputPanel()
        {
            RelativePanel outputPanel = new RelativePanel();
            var displayTitle = new TextBlock()
            {
                Text = "效果展示：",
                VerticalAlignment = VerticalAlignment.Center
            };

            canvas = new CanvasControl()
            {
                Width = 200,
                Height = 200,
            };

            displayCheckBox = new CheckBox();
            displayCheckBox.Name = nameof(displayCheckBox);
            BooleanToVisible btv = new BooleanToVisible();
            CreateBinding(null, nameof(displayCheckBox), new PropertyPath(nameof(CheckBox.IsChecked)), BindingMode.OneWay, canvas, CanvasAnimatedControl.VisibilityProperty, btv);

            RelativePanel.SetAlignRightWithPanel(displayCheckBox, true);

            RelativePanel.SetAlignBottomWith(displayTitle, displayCheckBox);
            RelativePanel.SetLeftOf(displayTitle, displayCheckBox);
            RelativePanel.SetAlignTopWithPanel(displayTitle, true);
            RelativePanel.SetAlignLeftWithPanel(displayTitle, true);

            RelativePanel.SetAlignBottomWithPanel(canvas, true);
            RelativePanel.SetBelow(canvas, displayTitle);


            outputPanel.Children.Add(displayTitle);
            outputPanel.Children.Add(displayCheckBox);
            outputPanel.Children.Add(canvas);

            displayCheckBox.IsChecked = true;
            this.controlContainer.Children.Add(outputPanel);
            timer.Interval = TimeSpan.FromMilliseconds(16);
            timer.Tick += Timer_Tick;
            timer.Start();
            canvas.Draw += Canvas_Draw;
            canvas.Unloaded += Canvas_Unloaded;

        }


        #region 设置指定控件和数据的绑定

        /// <summary>
        /// 设置slider 和指定的属性进行绑定
        /// </summary>
        /// <param name="slider"></param>
        /// <param name="source"></param>
        /// <param name="propertyPath"></param>
        protected void SetTextBoxSlider(TextBoxSlider slider, object source, string propertyPath)
        {
            CreateBinding(source, "", new PropertyPath(propertyPath), BindingMode.TwoWay, slider, TextBoxSlider.ValueProperty);
        }

        protected void SetComboBox(ComboBox comboBox, object itemsSource, object source, string propertyPath)
        {

            comboBox.ItemsSource = itemsSource;
            CreateBinding(source, "", new PropertyPath(propertyPath), BindingMode.TwoWay, comboBox, ComboBox.SelectedItemProperty);
        }

        protected void SetCheckBox(CheckBox checkBox, object source, string propertyPath)
        {
            CreateBinding(source, "", new PropertyPath(propertyPath), BindingMode.TwoWay, checkBox, CheckBox.IsCheckedProperty);
        }

        protected void SetVector2Control(Vector2Control vector2Control, object source, string propertyPath)
        {
            CreateBinding(source, "", new PropertyPath(propertyPath), BindingMode.TwoWay, vector2Control, Vector2Control.Vector2Property);
        }

        protected void SetVector4Control(Vector4Control vector4Control, object source, string propertyPath)
        {
            CreateBinding(source, "", new PropertyPath(propertyPath), BindingMode.TwoWay, vector4Control, Vector4Control.Vector4Property);
        }

        protected void SetMatrix3x2Control(Matrix3x2Control matrix3x2Control, object source, string propertyPath)
        {
            CreateBinding(source, "", new PropertyPath(propertyPath), BindingMode.TwoWay, matrix3x2Control, Matrix3x2Control.Matrix3x2Property);
        }

        protected void SetRectSlider(RectSlider rectSlider, object source, string propertyPath)
        {
            CreateBinding(source, "", new PropertyPath(propertyPath), BindingMode.TwoWay, rectSlider, RectSlider.RectProperty);

        }

        protected void SetColorPicker(ColorPicker colorPicker, object source, string propertyPath)
        {
            CreateBinding(source, "", new PropertyPath(propertyPath), BindingMode.TwoWay, colorPicker, ColorPicker.ColorProperty);

        }

        /// <summary>
        /// 创建绑定
        /// </summary>
        /// <param name="source">绑定的属性</param>
        /// <param name="elementName">元素名</param>
        /// <param name="path">属性路径</param>
        /// <param name="mode">绑定模式</param>
        /// <param name="target">绑定目标</param>
        /// <param name="dp">绑定的属性类型</param>
        protected void CreateBinding(Object source, string elementName, PropertyPath path, BindingMode mode, DependencyObject target, DependencyProperty dp, IValueConverter convert = null)
        {

            // 实例化 Binding 对象
            Binding binding = new Binding()
            {
                Source = source,
                ElementName = elementName, // textBox2 是延迟加载元素，将其与 textBox1 绑定后，textBox2 就会被加载
                Path = path,
                Mode = mode,
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
                Converter = convert
            };

            // 将目标对象的目标属性与指定的 Binding 对象关联
            BindingOperations.SetBinding(target, dp, binding);
        }


        /// <summary>
        /// 创建绑定
        /// </summary>
        /// <param name="source">绑定的属性</param>
        /// <param name="elementName">元素名</param>
        /// <param name="path">属性路径</param>
        /// <param name="target">绑定目标</param>
        /// <param name="dp">绑定的属性类型</param>
        protected void CreateBinding(Object source, string elementName, string path, DependencyObject target, DependencyProperty dp, IValueConverter convert = null)
        {
            CreateBinding(source, elementName, new PropertyPath(path), BindingMode.TwoWay, target, dp, convert);
        }


        #endregion



        /// <summary>
        /// 输出控件被拖动了
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void exporterDrag_DragStarting(UIElement sender, DragStartingEventArgs args)
        {

            EffectOutputInitial();
            OnDragExportInvoke();
        }

        /// <summary>
        /// 设置输出属性
        /// </summary>
        protected virtual void EffectOutputInitial()
        {
            OutputData od = new OutputData();
            od.ExporterData = EffectData;
            od.Type = OutputType.Effect;
            od.Exporter = this;
            od.ExportConnectElement = (ExporterDragControl)exporterDrag;
            outputData = od;
        }

        /// <summary>
        /// 效果改变
        /// </summary>
        protected virtual void EffectChangedInvoke()
        {
            EffectChanged?.Invoke(this);
        }



        /// <summary>
        /// 删除当前控件
        /// </summary>
        public override void Destroy()
        {
            base.Destroy();
            EffectData.Destroy();
            canvas = null;
            EffectData = null;

        }

        protected void Canvas_Unloaded(object sender, RoutedEventArgs e)
        {
            EffectData = null;
            if (Effect != null)
            {
                Effect.Dispose();
                Effect = null;
            }
        }





        /// <summary>
        /// 输出者删除指定的接收者
        /// </summary>
        /// <param name="connectElement"></param>
        public override void RemoveProvider(ConnectLineUIElement connectElement)
        {
            //删除连接线
            RemoveExportoneConnectElement(connectElement);
            var provider = (EffectControl)connectElement.Provider;
            EffectData.RemoveOutputSequene(provider.EffectData);
            if(ListExportoneConnectElement.Count < 1)
            {
                exporterDrag.SetDeConnectState();
            }
        }

      
    }
}
